#include <iostream>
#include <vector>
#include <string>
#include <iomanip>
#include <sstream>
#include <fstream>

using namespace std;

// 账单结构体：包含所有必要信息
struct Bill {
    char type;       // 'I'表示收入，'E'表示支出
    string date;     // 日期：YYYY-MM-DD
    double money;    // 金额（正数）
    string kind;     // 类别（工资/餐饮等）
    string note;     // 备注
};

// 预算结构体
struct Budget {
    string month;    // 月份：YYYY-MM
    double limit;    // 预算限额
};

// 全局变量存储数据
vector<Bill> allBills;    // 所有账单
vector<Budget> allBudgets;// 所有预算

// 函数声明（按功能分类）
void showMenu();                  // 显示菜单
void addIncome();                 // 记录收入
void addExpense();                // 记录支出
void showAll();                   // 显示所有账单
void queryBills();                // 查询账单
void setBudget();                 // 设置预算
void showReport();                // 月度统计
bool checkDate(string date);      // 检查日期格式
bool checkMoney(double money);    // 检查金额是否合法
void saveData();                  // 保存数据
void loadData();                  // 加载数据

int main() {
    loadData();  // 启动时加载已保存的数据
    int choice;

    while (true) {
        showMenu();
        cin >> choice;
        cin.ignore();  // 清除输入缓冲区的回车

        // 根据选择执行对应功能
        switch (choice) {
        case 1: addIncome(); break;
        case 2: addExpense(); break;
        case 3: showAll(); break;
        case 4: queryBills(); break;
        case 5: setBudget(); break;
        case 6: showReport(); break;
        case 7:
            saveData();  // 退出前保存数据
            cout << "谢谢使用，再见！" << endl;
            return 0;
        default:
            cout << "输入错误，请重新选择！" << endl;
            system("pause");  // 暂停一下让用户看清提示
        }
    }
}

// 显示主菜单
void showMenu() {
    system("cls");
    cout << "============================" << endl;
    cout << "      个人账单管理系统      " << endl;
    cout << "============================" << endl;
    cout << "1. 记录收入" << endl;
    cout << "2. 记录支出" << endl;
    cout << "3. 查看所有账单" << endl;
    cout << "4. 查询账单" << endl;
    cout << "5. 设置月度预算" << endl;
    cout << "6. 查看月度统计" << endl;
    cout << "7. 退出系统" << endl;
    cout << "============================" << endl;
    cout << "请输入选项(1-7)：";
}

// 记录收入
void addIncome() {
    system("cls");
    Bill b;
    b.type = 'I';  // 收入类型标记

    cout << "===== 记录收入 =====" << endl;

    // 输入日期（带格式检查）
    while (true) {
        cout << "请输入日期(YYYY-MM-DD)：";
        getline(cin, b.date);
        if (checkDate(b.date)) break;
        else cout << "日期格式错误！请重新输入" << endl;
    }

    // 输入金额（带合法性检查）
    while (true) {
        cout << "请输入收入金额：";
        cin >> b.money;
        if (checkMoney(b.money)) break;
        else cout << "金额必须是正数！请重新输入" << endl;
    }
    cin.ignore();  // 清除缓冲区

    // 输入类别和备注
    cout << "请输入收入类别(如：工资、奖金)：";
    getline(cin, b.kind);
    cout << "请输入备注(可选)：";
    getline(cin, b.note);

    // 保存到账单列表
    allBills.push_back(b);
    cout << "收入记录成功！" << endl;
    system("pause");
}

// 记录支出
void addExpense() {
    system("cls");
    Bill b;
    b.type = 'E';  // 支出类型标记
    cout << "===== 记录支出 =====" << endl;
    // 输入日期
    while (true) {
        cout << "请输入日期(YYYY-MM-DD)：";
        getline(cin, b.date);
        if (checkDate(b.date)) break;
        else cout << "日期格式错误！请重新输入" << endl;
    }

    // 输入金额
    while (true) {
        cout << "请输入支出金额：";
        cin >> b.money;
        if (checkMoney(b.money)) break;
        else cout << "金额必须是正数！请重新输入" << endl;
    }
    cin.ignore();

    // 输入类别和备注
    cout << "请输入支出类别(如：餐饮、交通)：";
    getline(cin, b.kind);
    cout << "请输入备注(可选)：";
    getline(cin, b.note);

    // 保存到账单列表
    allBills.push_back(b);
    cout << "支出记录成功！" << endl;
    system("pause");
}

// 查看所有账单（收入和支出分开显示）
void showAll() {
    system("cls");
    cout << "===== 所有收入记录 =====" << endl;
    cout << left << setw(12) << "日期"
        << setw(10) << "金额"
        << setw(15) << "类别"
        << "备注" << endl;
    cout << "-------------------------" << endl;

    // 先显示所有收入
    bool hasIncome = false;
    for (auto& bill : allBills) {
        if (bill.type == 'I') {
            hasIncome = true;
            cout << left << setw(12) << bill.date
                << setw(10) << bill.money
                << setw(15) << bill.kind
                << bill.note << endl;
        }
    }
    if (!hasIncome) cout << "暂无收入记录" << endl;

    // 再显示所有支出
    cout << endl << "===== 所有支出记录 =====" << endl;
    cout << left << setw(12) << "日期"
        << setw(10) << "金额"
        << setw(15) << "类别"
        << "备注" << endl;
    cout << "-------------------------" << endl;

    bool hasExpense = false;
    for (auto& bill : allBills) {
        if (bill.type == 'E') {
            hasExpense = true;
            cout << left << setw(12) << bill.date
                << setw(10) << bill.money
                << setw(15) << bill.kind
                << bill.note << endl;
        }
    }
    if (!hasExpense) cout << "暂无支出记录" << endl;

    system("pause");
}

// 查询账单（按日期或类别）
void queryBills() {
    system("cls");
    int way;
    cout << "===== 账单查询 =====" << endl;
    cout << "1. 按日期查询" << endl;
    cout << "2. 按类别查询" << endl;
    cout << "请选择查询方式：";
    cin >> way;
    cin.ignore();

    if (way == 1) {
        // 按日期查询
        string date;
        cout << "请输入要查询的日期(YYYY-MM-DD)：";
        getline(cin, date);
        if (!checkDate(date)) {
            cout << "日期格式错误！" << endl;
            system("pause");
            return;
        }

        // 显示查询结果
        cout << endl << "===== 收入查询结果 =====" << endl;
        bool hasIncome = false;
        for (auto& bill : allBills) {
            if (bill.type == 'I' && bill.date == date) {
                hasIncome = true;
                cout << "金额：" << bill.money
                    << "，类别：" << bill.kind
                    << "，备注：" << bill.note << endl;
            }
        }
        if (!hasIncome) cout << "无符合条件的收入记录" << endl;

        cout << endl << "===== 支出查询结果 =====" << endl;
        bool hasExpense = false;
        for (auto& bill : allBills) {
            if (bill.type == 'E' && bill.date == date) {
                hasExpense = true;
                cout << "金额：" << bill.money
                    << "，类别：" << bill.kind
                    << "，备注：" << bill.note << endl;
            }
        }
        if (!hasExpense) cout << "无符合条件的支出记录" << endl;

    }
    else if (way == 2) {
        // 按类别查询
        string kind;
        cout << "请输入要查询的类别：";
        getline(cin, kind);

        // 显示查询结果
        cout << endl << "===== 收入查询结果 =====" << endl;
        bool hasIncome = false;
        for (auto& bill : allBills) {
            if (bill.type == 'I' && bill.kind == kind) {
                hasIncome = true;
                cout << "日期：" << bill.date
                    << "，金额：" << bill.money
                    << "，备注：" << bill.note << endl;
            }
        }
        if (!hasIncome) cout << "无符合条件的收入记录" << endl;

        cout << endl << "===== 支出查询结果 =====" << endl;
        bool hasExpense = false;
        for (auto& bill : allBills) {
            if (bill.type == 'E' && bill.kind == kind) {
                hasExpense = true;
                cout << "日期：" << bill.date
                    << "，金额：" << bill.money
                    << "，备注：" << bill.note << endl;
            }
        }
        if (!hasExpense) cout << "无符合条件的支出记录" << endl;

    }
    else {
        cout << "查询方式错误！" << endl;
    }

    system("pause");
}

// 设置月度预算
void setBudget() {
    system("cls");
    Budget bg;
    cout << "===== 设置月度预算 =====" << endl;

    // 输入月份
    while (true) {
        cout << "请输入月份(YYYY-MM)：";
        getline(cin, bg.month);
        // 简单检查：长度7且第5个字符是'-'（如2024-09）
        if (bg.month.size() == 7 && bg.month[4] == '-') break;
        else cout << "月份格式错误！请重新输入" << endl;
    }

    // 输入预算金额
    while (true) {
        cout << "请输入该月支出预算限额：";
        cin >> bg.limit;
        if (bg.limit > 0) break;
        else cout << "预算必须是正数！请重新输入" << endl;
    }

    // 保存预算（如果已有该月预算则更新）
    bool updated = false;
    for (auto& b : allBudgets) {
        if (b.month == bg.month) {
            b.limit = bg.limit;
            updated = true;
            break;
        }
    }
    if (!updated) allBudgets.push_back(bg);

    cout << "预算设置成功！" << endl;
    system("pause");
}

// 查看月度统计
void showReport() {
    system("cls");
    string month;
    cout << "===== 月度统计 =====" << endl;
    cout << "请输入要统计的月份(YYYY-MM)：";
    getline(cin, month);
    if (month.size() != 7 || month[4] != '-') {
        cout << "月份格式错误！" << endl;
        system("pause");
        return;
    }

    // 计算该月总收入、总支出
    double totalIncome = 0, totalExpense = 0;
    for (auto& bill : allBills) {
        // 截取日期的前7位（如2024-09-15 -> 2024-09）
        if (bill.date.substr(0, 7) == month) {
            if (bill.type == 'I') totalIncome += bill.money;
            else totalExpense += bill.money;
        }
    }

    // 显示统计结果
    cout << endl << "===== " << month << " 统计结果 =====" << endl;
    cout << "总收入：" << totalIncome << " 元" << endl;
    cout << "总支出：" << totalExpense << " 元" << endl;
    cout << "结余：" << totalIncome - totalExpense << " 元" << endl;

    // 显示预算情况
    double budgetLimit = 0;
    for (auto& b : allBudgets) {
        if (b.month == month) {
            budgetLimit = b.limit;
            break;
        }
    }
    if (budgetLimit > 0) {
        cout << "月度预算：" << budgetLimit << " 元" << endl;
        cout << "剩余预算：" << budgetLimit - totalExpense << " 元" << endl;
        if (totalExpense > budgetLimit) {
            cout << "警告：已超出预算 " << totalExpense - budgetLimit << " 元！" << endl;
        }
    }
    else {
        cout << "该月未设置预算" << endl;
    }

    system("pause");
}

// 检查日期格式（简单验证）
bool checkDate(string date) {
    // 格式必须是YYYY-MM-DD（长度10，第5和第8位是'-'）
    if (date.size() != 10 || date[4] != '-' || date[7] != '-') {
        return false;
    }
    // 月份必须是01-12，日期必须是01-31（简化检查）
    string month = date.substr(5, 2);
    string day = date.substr(8, 2);
    if (month < "01" || month > "12") return false;
    if (day < "01" || day > "31") return false;
    return true;
}

// 检查金额是否为正数
bool checkMoney(double money) {
    return money > 0;
}

// 保存数据到文件
void saveData() {
    // 保存账单
    ofstream fout("bills.txt");
    for (auto& b : allBills) {
        fout << b.type << "|"
            << b.date << "|"
            << b.money << "|"
            << b.kind << "|"
            << b.note << endl;
    }
    fout.close();

    // 保存预算
    ofstream fout2("budget.txt");
    for (auto& b : allBudgets) {
        fout2 << b.month << "|" << b.limit << endl;
    }
    fout2.close();
}

// 从文件加载数据
void loadData() {
    // 加载账单
    ifstream fin("bills.txt");
    if (fin.is_open()) {
        string line;
        while (getline(fin, line)) {
            Bill b;
            // 按"|"分割字符串（简化处理）
            int pos1 = line.find("|");
            int pos2 = line.find("|", pos1 + 1);
            int pos3 = line.find("|", pos2 + 1);
            int pos4 = line.find("|", pos3 + 1);

            b.type = line[0];
            b.date = line.substr(pos1 + 1, pos2 - pos1 - 1);
            b.money = stod(line.substr(pos2 + 1, pos3 - pos2 - 1));
            b.kind = line.substr(pos3 + 1, pos4 - pos3 - 1);
            b.note = line.substr(pos4 + 1);

            allBills.push_back(b);
        }
        fin.close();
    }

    // 加载预算
    ifstream fin2("budget.txt");
    if (fin2.is_open()) {
        string line;
        while (getline(fin2, line)) {
            Budget bg;
            int pos = line.find("|");
            bg.month = line.substr(0, pos);
            bg.limit = stod(line.substr(pos + 1));
            allBudgets.push_back(bg);
        }
        fin2.close();
    }
}
